GPIO中断使用的Sample Code

  1. 在kernel/drivers/sstar/目录下新增目录test_gpioirq,放入mdrv_gpioirq.c。

  2. 修改Makefile,增加一行:oby-m += test_gpioirq/

  3. Make modules即可生成ko

    mdrv_gpioirq.c代码如下:

    #include < linux/module.h >  
    #include < linux/moduleparam.h >  
    #include < linux/types.h >  
    #include < linux/gpio.h >  
    #include < linux/interrupt.h >  
    #include "../include/ms_types.h"  
    //#include "../include/infinity6/gpio.h"  
    #include "../include/infinity6e/gpio.h"
    
    static int test_gpio_num = PAD_SAR_GPIO3;  
    static struct work_struct work;  
    static irqreturn_t gpio_keys_isr(int irq, void *dev_id)  
    {  
        struct irq_data *data;  
        int gpio_state;  
        int flag;  
        int gpio_num = *(int *)dev_id;  
        gpio_state = gpio_get_value(gpio_num);   
        printk("======gpio_keys_isr:irq=%d gpio num=%d state=%d=====\n",irq,gpio_num,gpio_state);  
        // 需要在中断服务程序中立即处理的动作放在这里
    
        if(!gpio_state)  
        {  
            flag=IRQF_TRIGGER_RISING;  
        }  
        else  
        {  
            flag=IRQF_TRIGGER_FALLING;  
        }  
        data = irq_get_irq_data(irq);  
        data->chip->irq_set_type(data, flag);  
        data->chip->irq_ack(data);
    
        schedule_work(&work);  
        return 0;  
    }  
    static void gpioirq_work_func(struct work_struct *work)  
    {  
        printk("Ok!\n");  
        //不需要在中断服务程序中立即处理,放在工作队列里处理。  
    }  
    int MDrv_GPIO_To_Irq(U8 u8IndexGPIO);  
    static int __init gpioirq_init(void)  
    {  
        const char *desc = "mdrv_gpioirq";  
        unsigned long irqflags;  
        int irq, error;   
        error = gpio_request(test_gpio_num, desc);  
        if (error < 0)  
        {  
            printk(KERN_ERR "failed to request GPIO %d, error %d\n", test_gpio_num, error);  
            goto fail2;  
        }  
        error = gpio_direction_input(test_gpio_num);  
        if (error < 0)  
        {  
            printk(KERN_ERR "failed to configure direction for GPIO %d, error %d\n", test_gpio_num, error);  
            goto fail3;  
        }  
        irq = MDrv_GPIO_To_Irq((U8)test_gpio_num);  
        if (irq < 0)   
        {  
            error = irq;  
            printk(KERN_ERR "Unable to get irq number for GPIO %d, error %d\n", test_gpio_num, error);  
            goto fail3;  
        }
    
        irqflags = IRQF_ONESHOT | IRQF_TRIGGER_FALLING ;
    
        INIT_WORK(&work, gpioirq_work_func);  
        error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, &test_gpio_num);  
        if (error < 0)   
        {  
            printk(KERN_ERR "Unable to claim irq %d; error %d\n", irq, error);  
            goto fail3;  
        }  
        printk(KERN_DEBUG"request_threaded_irq %d success\n",irq);  
        return 0;  
    fail3:  
        gpio_free(test_gpio_num);  
    fail2:  
        return error;  
    }
    
    static void __exit gpioirq_exit(void)  
    {  
        int irq=0;  
        irq = MDrv_GPIO_To_Irq((U8)test_gpio_num);  
        printk(KERN_DEBUG"free_irq %d\n",irq);  
        free_irq(irq, &test_gpio_num);  
        gpio_free(test_gpio_num);  
        cancel_work_sync(&work);  
    }
    
    module_init(gpioirq_init);  
    module_exit(gpioirq_exit);  
    MODULE_DESCRIPTION("Interrupted GPIO driver");  
    MODULE_LICENSE("GPL v2");